import loadingImg from "@/assets/gif/5dadd6e959321e9fb3639aa848cbc2fc.gif"
import LimitPromise from "@/utils/LimitPromise";
import localforage from "localforage";
import Axios from "axios";
import {FileUtils} from "@/utils/FileUtils";
import * as imageConversion from "image-conversion";
import {setImgSrc} from "@/components/CacheImg/cacheImgUseWork";

const limitPromise = new LimitPromise(3)
const cacheImgDb = localforage.createInstance({
  name: 'cacheImgDb'
}) // 二级缓存

// 缓存原图
const cacheImgDbSource = localforage.createInstance({
  name: 'cacheImgDbSource'
}) // 二级缓存


export interface ImgItem {
  url?: string;
  cacheUrl?: string;
  img?: HTMLImageElement;
  cacheId?: string;
}

/**
 * 主动清空图片缓存
 */
export async function clearImgCache() {
  return Promise.all([
    cacheImgDb.clear(),
    cacheImgDbSource.clear(),
  ])
}

const limitFunc = new LimitPromise(1)

async function imgSetSrc(imgs: ImgItem[], img: HTMLImageElement, url: string, cacheId: string, isSource: boolean) {
  const find = imgs.find(i => i.cacheId === cacheId)
  if (find) {
    if (find.url === 'loading') {
      // 第二次加载了就提前
      limitPromise.toFirstNest(url)
      find.img.src = loadingImg
      return;
    }
    if (find.url) {
      find.img.src = find.url
      return;
    }
  } else {
    let item: ImgItem = {
      url: 'loading',
      cacheUrl: url,
      cacheId,
      img,
    }
    imgs.push(item)
    limitFunc.call(async () => {
      let res = isSource ? await cacheImgDbSource.getItem(url) as string : await cacheImgDb.getItem(url) as string
      if (res) {
        if (isSource) {
          setImgSrc(useCacheImg.imgsSource, res, url)
        } else {
          setImgSrc(useCacheImg.imgs, res, url)
        }
        return res
      } else {
        await cacheImgDbSource.setItem(url, 'loading')
        await cacheImgDb.setItem(url, 'loading')
      }
    }, cacheId + 'getItem')
      .then((res) => {
        if(res) {
          return
        }
        limitPromise.call(async () => {
          let res1 = await Axios.get(url, {
            responseType: 'blob'
          })
          if (res1.status === 200) {
            let base64Source = await FileUtils.blob2Base64(res1.data)
            await cacheImgDbSource.setItem(url, base64Source)
            let base64 = await FileUtils.blob2Base64(await zipFile(res1.data))
            await cacheImgDb.setItem(url, base64)
            setImgSrc(useCacheImg.imgsSource, base64Source, url)
            setImgSrc(useCacheImg.imgs, base64, url)
          }
        }, url)
        limitPromise.toFirstNest(url)
      })
    img.src = loadingImg
  }
}

async function imgsDelTask(imgs: ImgItem[], cacheId: string) {
  const findIndex = imgs.findIndex(i => i.cacheId === cacheId)
  let delImgId = ''
  if (findIndex > -1) {
    delImgId = imgs.splice(findIndex, 1)[0].cacheUrl
  }
  limitFunc.delTask(cacheId + "getItem")
  let taskQueueItem = limitPromise.delTask(delImgId);
  if (taskQueueItem) {
    let url = taskQueueItem.id
    let newVar = await cacheImgDbSource.getItem(url);
    if (newVar && newVar === 'loading') {
      await cacheImgDbSource.removeItem(url)
    }
    let newVar1 = await cacheImgDb.getItem(url);
    if (newVar1 && newVar1 === 'loading') {
      await cacheImgDb.removeItem(url)
    }
  }
}

export const useCacheImg = {
  imgs: [] as ImgItem[], // 一级缓存
  imgsSource: [] as ImgItem[], // 缓存原图
  /**
   * @param img
   * @param url 图片的url
   * @param cacheId
   * @param zipAndCache 是否开启压缩并缓存
   */
  getUrl(img: HTMLImageElement, url: string, cacheId: string, zipAndCache: boolean = true) {
    if (!img) {
      return
    }
    if (zipAndCache === false) {
      imgSetSrc(this.imgsSource, img, url, cacheId, true)
      return;
    }
    imgSetSrc(this.imgs, img, url, cacheId, false)
  },
  delTask(cacheId) {
    return Promise.all([
      imgsDelTask(this.imgs, cacheId),
      imgsDelTask(this.imgsSource, cacheId)
    ])
  }
}


async function zipFile(file: Blob) {
  let blob = await imageConversion.compressAccurately(file, {
    size: 50,
  })
  return blob;
}
